import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Not } from 'typeorm';
import { UserSong } from './my-music.entity';
import {
  UserSongDto,
  UserSongResponseDto,
  UserMusicStatsDto,
} from './my-music.dto';
import { SongService } from '../song/song.service';
import { Song } from '../song/song.entity';
import { UserService } from '../user/user.service';

@Injectable()
export class MyMusicService {
  constructor(
    @InjectRepository(UserSong)
    private userSongRepository: Repository<UserSong>,
    @InjectRepository(Song)
    private songRepository: Repository<Song>,
    private songService: SongService,
    private userService: UserService,
  ) {}

  // 添加或更新用户的歌曲关系（收藏/播放）
  async upsertUserSong(
    userId: number,
    userSongDto: UserSongDto,
  ): Promise<UserSongResponseDto> {
    const { songId, isFavorite } = userSongDto;

    // 检查歌曲是否存在
    const song = await this.songService.findSongById(songId);
    if (!song) {
      throw new NotFoundException('歌曲不存在');
    }

    // 查找或创建用户歌曲关系
    let userSong = await this.userSongRepository.findOne({
      where: { userId, songId },
      relations: ['song'],
    });

    if (!userSong) {
      userSong = this.userSongRepository.create({
        userId,
        songId,
        isFavorite,
        playCount: 0,
      });
    } else {
      // 更新收藏状态
      if (isFavorite !== undefined) {
        userSong.isFavorite = isFavorite;
      }
    }

    await this.userSongRepository.save(userSong);

    return this.mapUserSongToResponseDto(userSong, song);
  }

  // 增加歌曲播放次数并记录用户播放历史
  async recordPlay(
    userId: number,
    songId: number,
  ): Promise<UserSongResponseDto> {
    // 检查歌曲是否存在
    const song = await this.songService.findSongById(songId);
    if (!song) {
      throw new NotFoundException('歌曲不存在');
    }
    // 查找或创建用户歌曲关系
    let userSong = await this.userSongRepository.findOne({
      where: { userId, songId },
    });
    if (!userSong) {
      userSong = this.userSongRepository.create({
        userId,
        songId,
        isFavorite: false,
        playCount: 1,
        lastPlayedAt: new Date(),
      });
    } else {
      userSong.playCount += 1;
      userSong.lastPlayedAt = new Date();
    }

    await this.userSongRepository.save(userSong);

    // 如果歌曲实体中有播放次数字段，也更新它
    if (song.plays !== undefined) {
      const songEntity = new Song();
      Object.assign(songEntity, song);
      songEntity.plays += 1;
      await this.songService.updateSong(songId, {
        plays: songEntity.plays,
      } as any);
    }

    userSong.song = song as any;
    return this.mapUserSongToResponseDto(userSong, song);
  }

  // 获取用户收藏的歌曲
  async getUserFavorites(userId: number): Promise<UserSongResponseDto[]> {
    const userSongs = await this.userSongRepository.find({
      where: { userId },
      relations: ['song'],
      order: { updatedAt: 'DESC' },
    });
    console.log(userSongs, userId);
    return userSongs.map((userSong) =>
      this.mapUserSongToResponseDto(userSong, userSong.song),
    );
  }

  // 获取用户的播放历史
  async getUserPlayHistory(
    userId: number,
    limit: number = 50,
  ): Promise<UserSongResponseDto[]> {
    const userSongs = await this.userSongRepository
      .createQueryBuilder('userSong')
      .leftJoinAndSelect('userSong.song', 'song')
      .leftJoinAndSelect('song.artist', 'artist')
      .leftJoinAndSelect('song.album', 'album')
      .where('userSong.userId = :userId', { userId })
      .andWhere('song.isDeleted = false')
      .andWhere('userSong.lastPlayedAt IS NOT NULL')
      .orderBy('userSong.lastPlayedAt', 'DESC')
      .take(limit)
      .getMany();

    return userSongs.map((userSong) =>
      this.mapUserSongToResponseDto(userSong, userSong.song),
    );
  }

  // 获取用户的音乐统计信息
  async getUserMusicStats(userId: number): Promise<UserMusicStatsDto> {
    // 获取收藏歌曲数量
    const favoritesCount = await this.userSongRepository.count({
      where: { userId, isFavorite: true },
    });

    // 获取总播放次数
    const totalPlaysResult = await this.userSongRepository
      .createQueryBuilder('userSong')
      .select('SUM(userSong.playCount)', 'totalPlays')
      .where('userSong.userId = :userId', { userId })
      .getRawOne();

    const totalPlays = totalPlaysResult
      ? parseInt(totalPlaysResult.totalPlays || '0')
      : 0;

    // 获取最近播放的歌曲
    const recentPlays = await this.userSongRepository
      .createQueryBuilder('userSong')
      .select([
        'userSong.songId',
        'userSong.lastPlayedAt',
        'song.title',
        'artist.id',
        'artist.name',
      ])
      .innerJoin('song', 'song', 'song.id = userSong.songId')
      .innerJoin('song.artist', 'artist', 'artist.id = song.artistId')
      .where(
        'userSong.userId = :userId AND userSong.lastPlayedAt IS NOT NULL AND song.isDeleted = false',
        { userId },
      )
      .orderBy('userSong.lastPlayedAt', 'DESC')
      .take(10)
      .getRawMany();

    const recentlyPlayed = recentPlays.map((play) => ({
      songId: play.userSong_songId,
      title: play.song_title,
      artist: {
        id: play.artist_id,
        name: play.artist_name,
      },
      playedAt: play.userSong_lastPlayedAt,
    }));

    return {
      totalFavorites: favoritesCount,
      totalPlays,
      recentlyPlayed,
    };
  }

  // 辅助方法：将实体映射到响应DTO
  private mapUserSongToResponseDto(
    userSong: UserSong,
    song: any,
  ): UserSongResponseDto {
    return {
      id: userSong.id,
      songId: userSong.songId,
      isFavorite: userSong.isFavorite,
      playCount: userSong.playCount,
      addedAt: userSong.addedAt,
      updatedAt: userSong.updatedAt,
      lastPlayedAt: userSong.lastPlayedAt,
      song: {
        id: song.id,
        title: song.title,
        artist: song.artist
          ? { id: song.artist.id, name: song.artist.name }
          : { id: 0, name: '未知艺术家' },
        album: song.album
          ? { id: song.album.id, title: song.album.title }
          : { id: 0, title: '未知专辑' },
        duration: song.duration,
        coverImageUrl: song.album?.coverImageUrl || song.coverImageUrl,
        audioUrl: song.audioUrl,
      },
    };
  }
}
